﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using SignalR.Client;
using SignalR.Client.Hubs;

namespace WP7SignalRHelperClient
{
    public class SignalRMessagingHub : ISignalRHub
    {
        #region "Members"

        IHubProxy SignalRMapHub;
        IHubProxy SignalRChatHub;
        IHubProxy SignalRGameScoreHub;
        IHubProxy SignalRObjSyncHub;

        // Use the specific port# for local server or URI if hosted.        
        HubConnection mapConnection = new HubConnection("http://localhost:49593/");
        HubConnection chatConnection = new HubConnection("http://localhost:49593/");
        HubConnection gameConnection = new HubConnection("http://localhost:49593/");
        HubConnection objConnection = new HubConnection("http://localhost:49593/");
        
        public event SignalRServerHandler SignalRServerNotification;

        #endregion

        #region "Constructor"

        public SignalRMessagingHub()
        {
            // Reference to SignalR Server Hub & Proxy.                      
            SignalRMapHub = mapConnection.CreateProxy("SignalRHubs.MapHub");
            SignalRChatHub = chatConnection.CreateProxy("SignalRHubs.ChatHub");
            SignalRGameScoreHub = gameConnection.CreateProxy("SignalRHubs.GameScoreHub");
            SignalRObjSyncHub = objConnection.CreateProxy("SignalRHubs.ObjectHub");
        }

        #endregion

        #region "Implementation"

        public virtual void MapIt(MapClient phoneToMap)
        {
            // Fire up SignalR Connection & share location.  
            mapConnection.Start().ContinueWith(task =>
            {
                if (task.IsFaulted)
                {
                    // Oopsie, do some error handling.
                }

                // Join the Server's list of mapped clients.
                SignalRMapHub.Invoke("JoinFromPhone", phoneToMap.PhoneClientId, phoneToMap.Latitude, phoneToMap.Longitude).Wait();                
            });
        }

        public virtual void UnMapIt(MapClient phoneToMap)
        {
            // Disconnect from Server & unmap.
            SignalRMapHub.Invoke("Disconnect", phoneToMap.PhoneClientId).Wait();
        }

        public virtual void JoinChat(ChatClient phoneChatMessage)
        {
            // Fire up SignalR Connection & join chatroom.  
            chatConnection.Start().ContinueWith(task =>
            {
                if (task.IsFaulted)
                {
                    // Oopsie, do some error handling.
                }

                // Join the Server's list of Chatroom clients.
                SignalRChatHub.Invoke("JoinFromPhone", phoneChatMessage.PhoneClientId, phoneChatMessage.ChatUserName).Wait();
                SignalRChatHub.Invoke("PushMessageToClients", phoneChatMessage.ChatUserName + " just joined!").Wait();
            });

            // Listen to chat events on SignalR Server & wire them up appropriately.
            SignalRChatHub.On<string>("addChatMessage", message =>
            {
                SignalREventArgs chatArgs = new SignalREventArgs();
                chatArgs.ChatMessageFromServer = message;

                // Raise custom event & let it bubble up.
                OnSignalRServerNotificationReceived(chatArgs);
            });
        }

        public virtual void Chat(ChatClient phoneChatMessage)
        {
            // Post message to Server Chatroom.
            SignalRChatHub.Invoke("PushMessageToClients", phoneChatMessage.ChatMessage).Wait();           
        }

        public virtual void LeaveChat(ChatClient phoneChatMessage)
        {
            // Leave the Server's Chatroom.
            SignalRChatHub.Invoke("Disconnect", phoneChatMessage.PhoneClientId, phoneChatMessage.ChatUserName).Wait();
            SignalRChatHub.Invoke("PushMessageToClients", phoneChatMessage.ChatUserName + " just left!").Wait();
        }

        public virtual void FollowLiveGame(GameScoreClient gameFollowingPhone)
        {
            // Fire up SignalR Connection & start following a live game.  
            gameConnection.Start().ContinueWith(task =>
            {
                if (task.IsFaulted)
                {
                    // Oopsie, do some error handling.
                }               
            });

            // Listen to Game score updates from SignalR Server & wire them up appropriately.
            SignalRGameScoreHub.On<int,int>("pushScores", (teamAScore, teamBScore) =>
            {
                SignalREventArgs gameScoreArgs = new SignalREventArgs();
                gameScoreArgs.TeamAScore = teamAScore;
                gameScoreArgs.TeamBScore = teamBScore;

                // Raise custom event & let it bubble up.
                OnSignalRServerNotificationReceived(gameScoreArgs);
            });
        }

        public virtual void StartObjectSync(ObjectSyncClient objSyncFromPhone)
        {
            // Fire up SignalR Connection & start object sync.  
            objConnection.Start().ContinueWith(task =>
            {
                if (task.IsFaulted)
                {
                    // Oopsie, do some error handling.
                }

                // Join object sync.
                SignalRObjSyncHub.Invoke("JoinFromPhone", objSyncFromPhone.PhoneClientId).Wait();
            });

            // Listen to Game score updates from SignalR Server & wire them up appropriately.
            SignalRObjSyncHub.On<CustomClass>("pushObject", customObject =>
            {
                SignalREventArgs objSyncArgs = new SignalREventArgs();
                objSyncArgs.CustomObject = customObject;

                // Raise custom event & let it bubble up.
                OnSignalRServerNotificationReceived(objSyncArgs);
            });
        }

        public virtual void DoObjectSync(ObjectSyncClient objSyncFromPhone)
        {
            // Post message to Server for object sync from phone.
            SignalRObjSyncHub.Invoke("PushObjectToClients", objSyncFromPhone.CustomObject).Wait();    
        }

        #endregion

        #region "Methods"

        public virtual void OnSignalRServerNotificationReceived(SignalREventArgs e)
        {
            if (SignalRServerNotification != null)
            {
                SignalRServerNotification(this, e);
            }
        }     

        #endregion
    }
}
